﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.Collections;
using System.Threading;



namespace Serialportsimulator
{

    public enum Framestatus : int
    {
        intactframe = 1,
        excessframe = 2,
        lackframe = 3
    }


    public partial class MCUsimulator : Form
    {
        ResponseFrame responseframe = new ResponseFrame();
        public static ArrayList stagingframe = new ArrayList();

        SerialPort spSend;   //用虚拟接口发送和接收数据
        SerialPort spReceive;
        public delegate void listviewdata(string text);//委托
        public listviewdata updatelistview;
        SerialPort serialPort1 = null;
        string Comname = null;
        int framestatus = 0;
        static bool LackFrameLength = false;
        public MCUsimulator()
        {

            InitializeComponent();
            updatelistview = new listviewdata(Updatelistview);//实例化委托对象
            this.FormClosing += new FormClosingEventHandler(MCUsimulator_FormClosing);
            //serialPort1.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);
            //检查是否含有串口  
            string[] str = SerialPort.GetPortNames();
            if (str == null)
            {
                MessageBox.Show("本机没有串口！", "Error");
                return;
            }

            //添加串口项目  
            foreach (string s in System.IO.Ports.SerialPort.GetPortNames())
            {
                //获取有多少个COM口  
                SerialportName.Items.Add(s);
                //串口设置默认选择项  
                SerialportName.SelectedIndex = 0;         //设置SerialportName的默认选项 
            }

        }

        private void Cleardata_Click(object sender, EventArgs e)
        {
            PortDataView.Items.Clear();
        }

        private void Open_ClosePort_Click(object sender, EventArgs e)
        {
            string text = Open_ClosePort.Text;
            if (null == serialPort1)
            {
                serialPort1 = new SerialPort(Comname, 115200, Parity.None, 8, StopBits.One);
            }
            if (Open_ClosePort.Text == "启动")
            {
                SerialportName.Enabled = false;
                serialPort1.Open();
                serialPort1.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);
                Open_ClosePort.Text = "停止";
            }
            else
            {
                SerialportName.Enabled = true;
                serialPort1.DataReceived -= null;
                serialPort1.Close();
                Open_ClosePort.Text = "启动";
            }
            // this.Open_ClosePort.Text = text == "停止" ? "启动" : "停止";
            //调试
            //  string readString = "123";
            //this.Invoke(updatelistview, readString);
        }

        private void PortDataView_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void SerialportName_SelectedIndexChanged(object sender, EventArgs e)
        {
            Comname = SerialportName.SelectedItem.ToString();
        }

        private void MCUsimulator_Load(object sender, EventArgs e)
        {

        }
        private void MCUsimulator_FormClosing(object sender, FormClosingEventArgs e)
        {
            SerialPort port = new SerialPort();
            DialogResult dr;
            dr = MessageBox.Show("确定要退出吗？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (dr == DialogResult.OK)
            {
                port.Close();
                e.Cancel = false; ;
            }
            else
            {
                e.Cancel = true;
            }

        }

        public static string ByteToHexStr(byte[] bytes) //函数,字节数组转16进制字符串
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    returnStr += bytes[i].ToString("X2");

                }
            }
            string txt = string.Join(" ", Regex.Matches(returnStr, @"..").Cast<Match>().ToList());
            returnStr = txt;
            return returnStr;
        }

        public static string ArrayListToHexStr(ArrayList[] arrayList) //函数,动态数组转16进制字符串
        {
            string returnStr = "";
            if (arrayList != null)
            {
                for (int i = 0; i < arrayList.Count(); i++)
                {
                    returnStr += arrayList[i].ToString();

                }
            }
            string txt = string.Join(" ", Regex.Matches(returnStr, @"..").Cast<Match>().ToList());
            returnStr = txt;
            return returnStr;
        }
        public static int bytesToInt2(byte[] src, int offset)
        {
            int value;
            //value = (int)(((src[offset] & 0xFF) << 24)
            //        | ((src[offset + 1] & 0xFF) << 16)
            //        | ((src[offset + 2] & 0xFF) << 8)
            //        | (src[offset + 3] & 0xFF));
            value = (int)((src[offset] & 0xFF));
            return value;
        }

        public static void ExtractFramedata(ArrayList IntactFrame, int framelength, byte[] bytes, out int status, out ArrayList Frame)
        {
            //
            Frame = new ArrayList();
            for (int m = 0; m < IntactFrame.Count; m++)
            {
                Frame.Add(IntactFrame[m]);
            }
        
           
            //解析算法
            int length = bytes.Length;
            if (framelength == length)
            {
                //帧正好完整
                //将完整帧存入动态数组
                for (int i = 0; i < length; i++)
                {
                    Frame.Add(bytes[i]);
                }
                status = 1;

            }
            else if (framelength < length)
            {
                //帧多余完整一帧
                for (int i = 0; i < framelength; i++)
                {
                    Frame.Add(bytes[i]);
                }
                //多余的帧存入全局动态数组
                for (int i = framelength; i < length; i++)
                {
                    stagingframe.Add(bytes[i]);
                }
                status = 2;

            }
            else
            {
                //帧小于完整一帧
                for (int i = 0; i < length; i++)
                {
                    Frame.Add(bytes[i]);
                }
                for (int i = 0; i < Frame.Count; i++)
                {
                    stagingframe.Add(Frame[i]);
                }

                status = 3;
            }


        }

        public static void AnalysisFrame(byte[] bytes, out ArrayList IntactFrame, out int status) //解析完整帧,返回帧数组
        {
            //创建动态数组
            
            IntactFrame = new ArrayList();
            status = 0;
            int stagingcount = stagingframe.Count;

            //将上次保存的帧传递给动态数组，同时清空全局数组

            for (int m = 0; m < stagingframe.Count; m++)
            {
                IntactFrame.Add(stagingframe[m]);
            }
            stagingframe.Clear();

            //解析算法
            int length = bytes.Length;
            int framelength = 0;
            switch (stagingcount)
            {
                case 0://E1开头
                   
                        if (bytesToInt2(bytes, 0) == 0xE1)
                        {
                            if (length > 2)
                            {
                                if (bytesToInt2(bytes, 1) == 0xC3)
                                {
                                    if (length > 4)
                                    {
                                        //帧长度高地位拼接
                                        framelength = Convert.ToInt16((bytes[2].ToString("X2") + bytes[3].ToString("X2")), 16);
                                        framelength = framelength + 6;
                                        //ExtractFramedata
                                        ExtractFramedata(IntactFrame, framelength, bytes, out status, out IntactFrame);
                                        break;
                                    }
                                    else
                                    {
                                        //该帧小于长度位
                                       
                                        //帧小于完整一帧
                                        for (int i = 0; i < length; i++)
                                        {
                                            IntactFrame.Add(bytes[i]);
                                        }
                                        for (int i = 0; i < IntactFrame.Count; i++)
                                        {
                                            stagingframe.Add(IntactFrame[i]);
                                        }

                                        status = 3;
                                    }

                                }
                                else
                                {
                                    //错误
                                    break;

                                }
                            }
                            else
                            {
                                //该帧小于长度位
                                for (int i = 0; i < length; i++)
                                {
                                    IntactFrame.Add(bytes[i]);
                                }
                                for (int i = 0; i < IntactFrame.Count; i++)
                                {
                                    stagingframe.Add(IntactFrame[i]);
                                }
                                status = 3;
                            }

                        }
                        else
                        {
                            //帧错误
                            break;
                        }
                     break;
                case 1://C3开始
                    if (bytesToInt2(bytes, 0) == 0xC3)
                    {
                        if (length >= 3)
                        {
                            //帧缺失   
                            //帧长度高地位拼接
                            framelength = Convert.ToInt16((bytes[1].ToString("X2") + bytes[2].ToString("X2")), 16);
                            framelength = framelength + 5;
                            //ExtractFramedata
                            ExtractFramedata(IntactFrame, framelength, bytes, out status, out IntactFrame);
                        }
                        else
                        {
                            //该帧小于长度
                            for (int i = 0; i < length; i++)
                            {
                                IntactFrame.Add(bytes[i]);
                            }
                            for (int i = 0; i < IntactFrame.Count; i++)
                            {
                                stagingframe.Add(IntactFrame[i]);
                            }
                          
                            status = 3;
                          
                        }

                    }
                    else
                    {
                        //帧错误
                    }
                    break;
                case 2: //新帧以长度高位开始

                    if (length >= 2)
                    {
                        //帧长度高地位拼接
                        framelength = Convert.ToInt16((bytes[0].ToString("X2") + bytes[1].ToString("X2")), 16);

                        framelength = framelength + 4;

                        //ExtractFramedata
                        ExtractFramedata(IntactFrame, framelength, bytes, out status, out IntactFrame);

                    }
                    else
                    {
                        //该帧小于长度
                        for (int i = 0; i < length; i++)
                        {
                            IntactFrame.Add(bytes[i]);
                        }
                        for (int i = 0; i < IntactFrame.Count; i++)
                        {
                            stagingframe.Add(IntactFrame[i]);
                        }
                      
                        status = 3;
                       
                    }

                    break;
                case 3: //新帧以长度低位开始

                    if (length >= 1)
                    {
                        //帧长度高地位拼接
                        framelength = Convert.ToInt16((IntactFrame[2].ToString() + bytes[0].ToString("X2")), 16);
                        framelength = framelength + 3;
                        //
                        //ExtractFramedata
                        ExtractFramedata(IntactFrame, framelength, bytes, out status, out IntactFrame);
                    }
                    else
                    {
                        //该帧小于长度
                        for (int i = 0; i < length; i++)
                        {
                            IntactFrame.Add(bytes[i]);
                        }
                        for (int i = 0; i < IntactFrame.Count; i++)
                        {
                            stagingframe.Add(IntactFrame[i]);
                        }
                      
                        status = 3;
                       
                    }
                    break;
                case 4: //上一帧到帧长度结尾，新帧以帧编号开始

                    //帧长度高地位拼接
                    framelength = Convert.ToInt16((IntactFrame[2].ToString() + IntactFrame[3].ToString()), 16);
                    framelength = framelength + 2;

                    //ExtractFramedata
                    ExtractFramedata(IntactFrame, framelength, bytes, out status, out IntactFrame);
                    break;
                default: //上一帧大于4字节
                    //帧长度高地位拼接
                    framelength = Convert.ToInt16((IntactFrame[2].ToString() + IntactFrame[3].ToString()), 16);
                    framelength = framelength + 6 - IntactFrame.Count;
                    //ExtractFramedata
                    ExtractFramedata(IntactFrame, framelength, bytes, out status, out IntactFrame);
                    break;
            }

        }
        //绑定的事件处理函数
        public void FrameView(int status, ArrayList IntactFrame)
        {
        //帧解析
         
            byte[] framebytes = new byte[IntactFrame.Count];
             string txt;
            switch (status)
            {
                case (int)Framestatus.intactframe:

                    IntactFrame.CopyTo(framebytes);
                    //字节转换为字符串,显示
                    txt = ByteToHexStr(framebytes);
                    this.Invoke(updatelistview, txt);
                    //响应帧、结果帧
                    if (ResponseModel.Checked == true)
                    {
                         ArrayList Response = new ArrayList();
                         ArrayList Result = new ArrayList();
                        //调用响应、结果函数。
                         responseframe.Response(framebytes, out Response, out Result);
                         byte[] ResFrame = new byte[Response.Count];
                         byte[] ResultFrame = new byte[Result.Count];
                         Response.CopyTo(ResFrame);
                         Result.CopyTo(ResultFrame);
                        //输出响应、结果，显示输出测试
                         txt = ByteToHexStr(ResFrame);
                         this.Invoke(updatelistview, txt);
                         serialPort1.Write(ResFrame, 0, ResFrame.Count());
                        if(Result.Count != 0)
                        {
                         Thread.Sleep(2000);
                         txt = ByteToHexStr(ResultFrame);
                         this.Invoke(updatelistview, txt);
                         serialPort1.Write(ResultFrame, 0, ResultFrame.Count());
                        

                        }
                                                
                    }

                    status = 0;
                    break;

                case (int)Framestatus.excessframe:

                    IntactFrame.CopyTo(framebytes);
                    //字节转换为字符串,显示
                    txt = ByteToHexStr(framebytes);
                    this.Invoke(updatelistview, txt);

                    //对多余的部分再进行解析
                    byte[] bytes = new byte[stagingframe.Count];
                    stagingframe.CopyTo(bytes);
                    stagingframe.Clear();
                    AnalysisFrame(bytes, out IntactFrame, out status);
                    //解析处理
                    FrameView(status, IntactFrame);

                    break;

                case (int)Framestatus.lackframe:
                    status = 0;
                    break;

                default:
                    break;
            }

        }

        void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int count = serialPort1.BytesToRead;
            int status = 0;
            byte[] bytes = new byte[count];
            //读取串口字节
            serialPort1.Read(bytes, 0, count);
            //帧解析
            ArrayList IntactFrame = new ArrayList();
            AnalysisFrame(bytes, out IntactFrame, out status);
          
            //byte[] framebytes = new byte[IntactFrame.Count];
            //string txt;
            FrameView(status, IntactFrame);
           
        }


        //显示数据
        public void Updatelistview(string text)
        {
            this.PortDataView.BeginUpdate();   //数据更新，
            ListViewItem lvi = new ListViewItem();
            int i = PortDataView.Items.Count;
            i++;
            lvi.Text = i.ToString();
            lvi.SubItems.Add(text);
            this.PortDataView.Items.Add(lvi);
            this.PortDataView.EndUpdate();  //结束数据处理，UI界面一次性绘制。

        }





    }
}
